/*
 * Copyright (C) 2011-2012 Andrew Wells
 *
 * Licensed under the GNU License, Version 3
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/copyleft/gpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Dungeons & Dragons Copyright (C) Wizards of the Coast. I do not claim
 * the right to any information used from their books or resources.
 */

package com.trace.wells.charactertracker;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;

public class CharacterClass implements Serializable {

	private static final long serialVersionUID = 1L;

	//The total number of levels the character has achieved 
	private int level;

	//this VERY important array keeps track of how many levels the character has advanced in each class
	private int[] characterClassLevelsArray = new int[11];

	//Contains a string containing all the classes the character has trained in
	private String classDescriptionString;

	//These are the sum total of the character's current bonuses based off the single or multiple classes they could be
	private String baseAttackBonusString;

	//The specific attack bonus strings
	private String meleeAttackBonusString;
	private String rangedAttackBonusString;

	//Values for saving throws stored here
	private int[] savingThrowValues = new int[3];

	//The spellListItems ArrayList containing all the spells that character has prepared for the day
	private ArrayList<SpellListItem> spellListItemArray;

	private boolean[][] hasBeenCastArray;

	//Determines what screen to show the user
	private int[] characterMagicType;

	//The maximum number of spell levels of the character for each class
	//This is used to generate the spellBook expandable list views for each class
	private int[] maximumSpellLevels;

	//A 2D array containing the current spells that character can cast in each class
	private int[][] maxSpellsPerDayArray = new int[ConstantHelper.CLASS_NUMBER_MAX][ConstantHelper.SPELL_LEVEL_MAX];

	//A 2D array containing the remaining number of spells that that character can cast for each class
	private int[][] spellsCastsRemainingArray = new int[ConstantHelper.CLASS_NUMBER_MAX][ConstantHelper.SPELL_LEVEL_MAX];

	//A 2D array containing the number of spells a "special" magic type of character can know
	private int[][] spellsKnownArray = new int[ConstantHelper.CLASS_NUMBER_MAX][ConstantHelper.SPELL_LEVEL_MAX];

	private String beginningClass;

	//Default constructor
	public CharacterClass() {
	}

	/**
	 * This function is called when the character is created in the
	 * CreateCharacter activity. It will only be called once. Every other time,
	 * a level up function will be called
	 */
	public CharacterClass(String charClass, int level, int[] abilityModifierArray, int size) {
		this.level = level;
		characterClassLevelsArray = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
		int characterInteger = ConstantHelper.classStringToClassInt(charClass);
		characterClassLevelsArray[characterInteger]++;

		beginningClass = charClass;

		characterMagicType = calculateCharacterClassMagicType(characterClassLevelsArray);

		//Gets the base amount of casts per day
		maxSpellsPerDayArray = getBaseClassMaxSpellsPerDay(characterClassLevelsArray);

		//Gets the additional casts per day based on the character's ability modifiers
		maxSpellsPerDayArray = addBonusModifiersToBaseSpellsPerDay(characterClassLevelsArray, maxSpellsPerDayArray, abilityModifierArray);

		//Set as the same values as max Spells
		spellsCastsRemainingArray = copyMaxSpellsPerDayArray();

		//Returns an integer array containing the maximum number of spell levels for each class
		maximumSpellLevels = setMaximumSpellLevels(maxSpellsPerDayArray, characterClassLevelsArray);

		//Get the spells known for the character
		spellsKnownArray = getSpellsKnownArray(characterClassLevelsArray);

		//Gets the saving throw values for the character
		savingThrowValues = calcuateCharacterSavingThrowsValues(characterClassLevelsArray, abilityModifierArray);

		//Gets a description of the character (i.e. "Sorcerer-1/Fighter-3" for a level 1 sorcerer and level 3 fighter)
		classDescriptionString = setClass(characterClassLevelsArray);

		//Returns the base AttackBonus
		baseAttackBonusString = calculateCharacterBaseAttackBonus();

		String[] tempAttackBonus = calculateCharacterMeleeRangedBonus(abilityModifierArray, size);

		meleeAttackBonusString = tempAttackBonus[0];
		rangedAttackBonusString = tempAttackBonus[1];

		setSpellListItemArray(new ArrayList<SpellListItem>());

	}

	public void levelUpCharacterClass(String charClass, int[] abilityModifierArray, int size) {

		//Level up!
		this.level += 1;

		int characterInteger = ConstantHelper.classStringToClassInt(charClass);

		characterClassLevelsArray[characterInteger]++;

		characterMagicType = calculateCharacterClassMagicType(characterClassLevelsArray);

		//Gets the base amount of casts per day
		maxSpellsPerDayArray = getBaseClassMaxSpellsPerDay(characterClassLevelsArray);

		//Gets the additional casts per day based on the character's ability modifiers
		maxSpellsPerDayArray = addBonusModifiersToBaseSpellsPerDay(characterClassLevelsArray, maxSpellsPerDayArray, abilityModifierArray);

		//Does the above 2 lines in 1 line
		spellsCastsRemainingArray = copyMaxSpellsPerDayArray();

		//Returns an integer array containing the maximum number of spell levels for each class
		maximumSpellLevels = setMaximumSpellLevels(maxSpellsPerDayArray, characterClassLevelsArray);

		//Get the spells known for the character
		spellsKnownArray = getSpellsKnownArray(characterClassLevelsArray);

		//Gets the saving throw values for the character
		savingThrowValues = calcuateCharacterSavingThrowsValues(characterClassLevelsArray, abilityModifierArray);

		//Gets a description of the character (i.e. "Sorcerer-1/Fighter-3" for a level 1 sorcerer and level 3 fighter)
		classDescriptionString = setClass(characterClassLevelsArray);

		//Returns the base AttackBonus
		baseAttackBonusString = calculateCharacterBaseAttackBonus();

		String[] tempAttackBonus = calculateCharacterMeleeRangedBonus(abilityModifierArray, size);

		meleeAttackBonusString = tempAttackBonus[0];
		rangedAttackBonusString = tempAttackBonus[1];
	}

	private int[][] copyMaxSpellsPerDayArray() {
		int[][] returnArray = new int[ConstantHelper.CLASS_NUMBER_MAX][];

		for (int i = 0; i < ConstantHelper.CLASS_NUMBER_MAX; i++) {
			returnArray[i] = new int[maxSpellsPerDayArray[i].length];
			for (int j = 0; j < maxSpellsPerDayArray[i].length; j++) {
				returnArray[i][j] = maxSpellsPerDayArray[i][j];
			}
		}
		return returnArray;
	}

	//public int getFree

	public int[] getMaximumCastsPerDayArray(int currentSpellBookView) {
		int[] tempMaxSpellsPerDay = this.maxSpellsPerDayArray[currentSpellBookView];
		int[] classMaxSpellsPerDayArray = new int[ConstantHelper.SPELL_LEVEL_MAX];
		for (int i = 0; i < classMaxSpellsPerDayArray.length; i++) {
			classMaxSpellsPerDayArray[i] = tempMaxSpellsPerDay[i];
		}
		return classMaxSpellsPerDayArray;
	}

	/**
	 * 
	 * @param tempMaxSpellsPerDayArray
	 * @param tempCharacterClassLevelsArray
	 * @return
	 */
	private int[] setMaximumSpellLevels(int[][] tempMaxSpellsPerDayArray, int[] tempCharacterClassLevelsArray) {
		int[] returnMaxSpellLevels = new int[ConstantHelper.CLASS_NUMBER_MAX];
		for (int i = 0; i < ConstantHelper.CLASS_NUMBER_MAX; i++) {
			if (tempCharacterClassLevelsArray[i] > 0) {
				int spellClassTotoalLevel = 0;
				for (int j = 0; j < tempMaxSpellsPerDayArray[i].length; j++) {
					if (tempMaxSpellsPerDayArray[i][j] > 0)
						spellClassTotoalLevel++;
				}
				returnMaxSpellLevels[i] = spellClassTotoalLevel;
			}
		}
		return returnMaxSpellLevels;
	}

	/**
	 * Receives the CharacterClassLevelsArray and determines the saving throw
	 * values of the character
	 * 
	 * @param tempCharacterClassLevelsArray
	 * @return array containing the sum saving throw totals
	 */
	public int[] calcuateCharacterSavingThrowsValues(int[] tempCharacterClassLevelsArray, int[] tempAbilityModifierArray) {
		//fortitude, reflex, will BSB array
		int[] baseSaveBonuses = new int[3];
		//for each class that exists
		for (int i = 0; i < tempCharacterClassLevelsArray.length; i++) {

			//If one of the characterClassLevel array elements are > 1 (If that character has atleast one level invested in a class)
			if (tempCharacterClassLevelsArray[i] > 0) {

				//This call receives the base saving throws table based on the character class
				int[][] baseSaveTable = ConstantHelper.generateBaseSavingThrowsTable(ConstantHelper.CLASS_BASE_SAVING_THROWS[i]);

				//These variables keep a count of the total saving throw values so far.

				//Fortitude
				baseSaveBonuses[0] += baseSaveTable[0][tempCharacterClassLevelsArray[i]];

				//Reflex
				baseSaveBonuses[1] += baseSaveTable[1][tempCharacterClassLevelsArray[i]];

				//Will
				baseSaveBonuses[2] += baseSaveTable[2][tempCharacterClassLevelsArray[i]];
			}
		}

		//Apply modifiers to the character
		baseSaveBonuses[0] += tempAbilityModifierArray[2];
		baseSaveBonuses[1] += tempAbilityModifierArray[1];
		baseSaveBonuses[2] += tempAbilityModifierArray[4];

		//Return the array containing the total value of the saving throws
		return baseSaveBonuses;
	}

	//Gets the total, current and hitdie to the required number for that class.
	public int getHitDieForClass(String charClass) {
		int hitDie = 0;
		if (charClass.equals(ConstantHelper.CLASS_BARBARIAN)) {
			hitDie = 12;
		} else if (charClass.equals(ConstantHelper.CLASS_BARD)) {
			hitDie = 6;
		} else if (charClass.equals(ConstantHelper.CLASS_CLERIC)) {
			hitDie = 8;
		} else if (charClass.equals(ConstantHelper.CLASS_DRUID)) {
			hitDie = 8;
		} else if (charClass.equals(ConstantHelper.CLASS_FIGHTER)) {
			hitDie = 10;
		} else if (charClass.equals(ConstantHelper.CLASS_MONK)) {
			hitDie = 8;
		} else if (charClass.equals(ConstantHelper.CLASS_PALADIN)) {
			hitDie = 10;
		} else if (charClass.equals(ConstantHelper.CLASS_RANGER)) {
			hitDie = 8;
		} else if (charClass.equals(ConstantHelper.CLASS_ROGUE)) {
			hitDie = 6;
		} else if (charClass.equals(ConstantHelper.CLASS_SORCERER)) {
			hitDie = 4;
		} else if (charClass.equals(ConstantHelper.CLASS_WIZARD)) {
			hitDie = 4;
		} else
			hitDie = 0;
		return hitDie;
	}

	//Sets the class string of the character to a value containing all the classes they have multiclassed in.
	public String setClass(int[] tempCharacterClassLevelsArray) {
		String fullClassName = "";
		ArrayList<String> classNamesArray = new ArrayList<String>();
		for (int i = 0; i < ConstantHelper.CLASS_NUMBER_MAX; i++) {
			int classLevelValue = tempCharacterClassLevelsArray[i];
			if (classLevelValue > 0) {
				classNamesArray.add(ConstantHelper.classIntToString(i) + "-" + classLevelValue);
			}
		}
		Collections.sort(classNamesArray);
		for (String s : classNamesArray) {
			fullClassName += s + " / ";
		}
		//Gets rid of the trailing 
		fullClassName = fullClassName.trim();
		return fullClassName.substring(0, (fullClassName.length() - 1));
	}

	/**
	 * Receives a the character level array and returns the appropriate 2D array
	 * containing the number of spell casts each class can make.
	 * 
	 * @param class level array
	 * @return Number of max Casts per class
	 */
	public int[][] getBaseClassMaxSpellsPerDay(int[] level) {
		int[][] spellCastReturnArray = new int[ConstantHelper.CLASS_NUMBER_MAX][ConstantHelper.SPELL_LEVEL_MAX];

		//This class does not have any magic-per-day casts
		spellCastReturnArray[1] = ConstantHelper.SPELL_DAY_BARD[level[1]];
		spellCastReturnArray[2] = ConstantHelper.SPELL_DAY_CLERIC_DOMAIN[level[2]];
		spellCastReturnArray[3] = ConstantHelper.SPELL_DAY_DRUID[level[3]];
		//This class does not have any magic-per-day casts
		//This class does not have any magic-per-day casts
		spellCastReturnArray[6] = ConstantHelper.SPELL_DAY_PALADIN[level[6]];
		spellCastReturnArray[7] = ConstantHelper.SPELL_DAY_RANGER[level[7]];
		//This class does not have any magic-per-day casts
		spellCastReturnArray[9] = ConstantHelper.SPELL_DAY_SORCERER[level[9]];
		spellCastReturnArray[10] = ConstantHelper.SPELL_DAY_WIZARD[level[10]];

		return spellCastReturnArray;
	}

	/**
	 * Adds additional spells per day to the spellsPerDay array
	 * 
	 * @param tempCharacterClassLevelsArray
	 * 
	 * @param tempMaxSpellsPerDayArray
	 * @param abilityModifierArray
	 * @return
	 */
	private int[][] addBonusModifiersToBaseSpellsPerDay(int[] tempCharacterClassLevelsArray, int[][] tempMaxSpellsPerDayArray, int[] abilityModifierArray) {
		int modifierNumberToUse;

		for (int i = 0; i < tempCharacterClassLevelsArray.length; i++) {
			if (tempCharacterClassLevelsArray[i] > 0) {
				if (i == ConstantHelper.CLASS_NUMBER_BARD) {
					modifierNumberToUse = abilityModifierArray[5];
				} else if (i == ConstantHelper.CLASS_NUMBER_CLERIC) {
					modifierNumberToUse = abilityModifierArray[4];
				} else if (i == ConstantHelper.CLASS_NUMBER_DRUID) {
					modifierNumberToUse = abilityModifierArray[4];
				} else if (i == ConstantHelper.CLASS_NUMBER_PALADIN) {
					modifierNumberToUse = abilityModifierArray[4];
				} else if (i == ConstantHelper.CLASS_NUMBER_RANGER) {
					modifierNumberToUse = abilityModifierArray[4];
				} else if (i == ConstantHelper.CLASS_NUMBER_SORCERER) {
					modifierNumberToUse = abilityModifierArray[5];
				} else if (i == ConstantHelper.CLASS_NUMBER_WIZARD) {
					modifierNumberToUse = abilityModifierArray[3];
				} else {
					modifierNumberToUse = -1;
				}

				if (modifierNumberToUse != -1) {
					int[] bonusSpellsArray = ConstantHelper.BONUS_SPELLS[modifierNumberToUse];
					for (int j = 1; j < bonusSpellsArray.length - 1; j++) {
						if (bonusSpellsArray[j] != -1 && tempMaxSpellsPerDayArray[i][j - 1] != -1)
							tempMaxSpellsPerDayArray[i][j - 1] += bonusSpellsArray[j];
					}
				}
			}
		}
		return tempMaxSpellsPerDayArray;
	}

	/**
	 * Gets the specific magicType for each characterClassLevelArray element
	 * 
	 * @param tempCharacterClassLevelsArray
	 * @return
	 */
	public int[] calculateCharacterClassMagicType(int[] tempCharacterClassLevelsArray) {
		int[] classLevelArray = tempCharacterClassLevelsArray;
		int[] characterMagicType = new int[ConstantHelper.CLASS_NUMBER_MAX];
		boolean isMagic = false;
		//		boolean isNormalMagic = false;
		//		boolean isSpecialMagic = false;
		for (int i = 0; i < tempCharacterClassLevelsArray.length; i++) {
			if (classLevelArray[ConstantHelper.CLASS_NUMBER_CLERIC] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_DRUID] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_PALADIN] > 0
					|| classLevelArray[ConstantHelper.CLASS_NUMBER_RANGER] > 0 || classLevelArray[10] > 0)
				characterMagicType[i] = ConstantHelper.CHAR_TYPE_NORMAL_MAGIC;
			else if (classLevelArray[ConstantHelper.CLASS_NUMBER_BARD] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_SORCERER] > 0)
				characterMagicType[i] = ConstantHelper.CHAR_TYPE_SPECIAL_MAGIC;
			else
				characterMagicType[i] = ConstantHelper.CHAR_TYPE_NO_MAGIC;
		}
		return characterMagicType;
	}

	public int calculateOverallCharacterClassMagicType(int[] tempCharacterClassLevelsArray) {
		int[] classLevelArray = tempCharacterClassLevelsArray;
		int returnmagicType = ConstantHelper.CHAR_TYPE_NO_MAGIC;
		for (int i = 0; i < tempCharacterClassLevelsArray.length; i++) {
			if (classLevelArray[ConstantHelper.CLASS_NUMBER_CLERIC] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_DRUID] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_PALADIN] > 0
					|| classLevelArray[ConstantHelper.CLASS_NUMBER_RANGER] > 0 || classLevelArray[10] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_BARD] > 0
					|| classLevelArray[ConstantHelper.CLASS_NUMBER_SORCERER] > 0) {
				returnmagicType = ConstantHelper.CHAR_TYPE_MAGIC;
				break;
			}
		}
		return returnmagicType;
	}

	public int getSpeficficCharacterClassMagicType(int c) {
		int returnValue = -1;
		if (c == 2 || c == 3 || c == 6 || c == 7 || c == 10)
			returnValue = ConstantHelper.CHAR_TYPE_NORMAL_MAGIC;
		else if (c == 1 || c == 9) {
			returnValue = ConstantHelper.CHAR_TYPE_SPECIAL_MAGIC;
		}
		return returnValue;
	}

	/**
	 * Determines if the character has any magical capabilities at all
	 * 
	 * @return
	 */
	public boolean characterIsMagical() {
		int[] classLevelArray = characterClassLevelsArray;
		boolean isMagic = false;
		if (classLevelArray[ConstantHelper.CLASS_NUMBER_CLERIC] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_DRUID] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_PALADIN] > 0
				|| classLevelArray[ConstantHelper.CLASS_NUMBER_RANGER] > 0 || classLevelArray[10] > 0)
			isMagic = true;
		else if (classLevelArray[ConstantHelper.CLASS_NUMBER_BARD] > 0 || classLevelArray[ConstantHelper.CLASS_NUMBER_SORCERER] > 0)
			isMagic = true;
		else
			isMagic = false;
		return isMagic;
	}

	/**
	 * Gets the number of knowable spells for the "special" magic group (Bard
	 * and Sorcerer) Takes into account the character's modifiers to adjust and
	 * additional spell they may have on thieir new level
	 * 
	 * @param characterLevelArray
	 * @return
	 */
	private int[][] getSpellsKnownArray(int[] characterLevelArray) {
		int[][] tempSpellsKnownArray = new int[ConstantHelper.CLASS_NUMBER_MAX][ConstantHelper.SPELL_LEVEL_MAX];
		tempSpellsKnownArray[ConstantHelper.CLASS_NUMBER_BARD] = ConstantHelper.SPELLS_KNOWN_BARD[characterLevelArray[ConstantHelper.CLASS_NUMBER_BARD]];
		tempSpellsKnownArray[ConstantHelper.CLASS_NUMBER_SORCERER] = ConstantHelper.SPELLS_KNOWN_SORCERER[characterLevelArray[ConstantHelper.CLASS_NUMBER_SORCERER]];

		//This section was used to boost the character's spells per day, but I think I will do this in a different function		
		//		if (characterLevelArray[ConstantHelper.CLASS_NUMBER_BARD] == 2)
		//			tempSpellsKnownArray[ConstantHelper.CLASS_NUMBER_BARD][1]++;

		//		//19 is used because after the 6th spell level for Bard, there is no other spell levels to go to
		//		for (int i = 4; i < 19; i++) {
		//			if (i % 3 == 1) {
		//				tempSpellsKnownArray[ConstantHelper.CLASS_NUMBER_BARD][spellLevelCounter]++;
		//				spellLevelCounter++;
		//			}
		//		}

		return tempSpellsKnownArray;
	}

	public String calculateCharacterBaseAttackBonus() {
		int[] temporaryCharacterClassLevelArray = characterClassLevelsArray;
		int[] classBaseAttackBonusesArray = ConstantHelper.CLASS_BASE_ATTACK_BONUSES;
		int totalBAB = 0;

		for (int i = 0; i < classBaseAttackBonusesArray.length; i++) {
			int[] classSpecificbonusArray = ConstantHelper.generateBaseAttackBonusArray(classBaseAttackBonusesArray[i]);
			totalBAB += classSpecificbonusArray[temporaryCharacterClassLevelArray[i]];
		}
		String baseAttackBonusString = generateBaseAttackBonusStringArray(totalBAB);
		return baseAttackBonusString;
	}

	public String[] calculateCharacterMeleeRangedBonus(int[] abilityModifierArray, int size) {
		int[] temporaryCharacterClassLevelArray = characterClassLevelsArray;
		int[] classBaseAttackBonusesArray = ConstantHelper.CLASS_BASE_ATTACK_BONUSES;
		int totalBAB = 0;

		for (int i = 0; i < classBaseAttackBonusesArray.length; i++) {
			int[] classSpecificbonusArray = ConstantHelper.generateBaseAttackBonusArray(classBaseAttackBonusesArray[i]);
			totalBAB += classSpecificbonusArray[temporaryCharacterClassLevelArray[i]];
		}
		String[] attackBonuses = new String[2];
		if (totalBAB + abilityModifierArray[0] + size > -1)
			attackBonuses[0] = "+" + String.valueOf(totalBAB + abilityModifierArray[0] + size);
		else
			attackBonuses[0] = "-" + String.valueOf(totalBAB + abilityModifierArray[0] + size);

		if (totalBAB + abilityModifierArray[1] + size > -1)
			attackBonuses[1] = "+" + String.valueOf(totalBAB + abilityModifierArray[1] + size);
		else
			attackBonuses[1] = "-" + String.valueOf(totalBAB + abilityModifierArray[1] + size);
		//		attackBonuses[0] = String.valueOf(totalBAB + abilityModifierArray[0] + size);
		//		attackBonuses[1] = String.valueOf(totalBAB + abilityModifierArray[1] + size);

		return attackBonuses;
	}

	public static String generateBaseAttackBonusStringArray(int totalBAB) {

		// Temporary bab array to be returned to the calling function
		int[] tempBaseAttackBonusArray = new int[4];
		String returnString;

		// Modifiers used to calculate upper level BABs
		int mod1 = 5;
		int mod2 = 10;
		int mod3 = 15;

		// Empty String used to generate a BAB String for the character
		StringBuffer s = new StringBuffer();

		if (totalBAB > 0) {
			tempBaseAttackBonusArray[0] = totalBAB;
			if (totalBAB > 5)
				tempBaseAttackBonusArray[1] = totalBAB - mod1;
			if (totalBAB > 10)
				tempBaseAttackBonusArray[2] = totalBAB - mod2;
			if (totalBAB > 15)
				tempBaseAttackBonusArray[3] = totalBAB - mod3;

			for (int i = 0; i < tempBaseAttackBonusArray.length; i++) {
				// System.out.println(tempBaseAttackBonusArray[i]);
				if (tempBaseAttackBonusArray[i] > 0) {
					s.append("+" + tempBaseAttackBonusArray[i] + "/");
				}
			}
		} else
			s.append("+0/");

		returnString = s.toString();
		return returnString.substring(0, (s.length() - 1));
	}

	public int getSkillPointCount(int level, int intmod, String charClass) {
		boolean isBegin = false;
		int retVal = 0;
		if (level == 1)
			isBegin = true;

		if (charClass.equals(ConstantHelper.CLASS_BARBARIAN)) {
			retVal = isBegin ? (4 + intmod) * 4 : (4 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_BARD)) {
			retVal = isBegin ? (6 + intmod) * 4 : (6 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_CLERIC)) {
			retVal = isBegin ? (2 + intmod) * 4 : (2 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_DRUID)) {
			retVal = isBegin ? (4 + intmod) * 4 : (4 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_FIGHTER)) {
			retVal = isBegin ? (2 + intmod) * 4 : (2 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_MONK)) {
			retVal = isBegin ? (4 + intmod) * 4 : (4 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_PALADIN)) {
			retVal = isBegin ? (2 + intmod) * 4 : (2 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_RANGER)) {
			retVal = isBegin ? (6 + intmod) * 4 : (6 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_ROGUE)) {
			retVal = isBegin ? (8 + intmod) * 4 : (8 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_SORCERER)) {
			retVal = isBegin ? (2 + intmod) * 4 : (2 + intmod);
		} else if (charClass.equals(ConstantHelper.CLASS_WIZARD)) {
			retVal = isBegin ? (2 + intmod) * 4 : (2 + intmod);
		} else
			;
		return retVal;
	}

	/**
	 * Returns the number of free slots for a class's spell list. ONLY FOR
	 * SPECIAL MAGIC TYPE
	 * 
	 * @param classNumberRepresentation
	 * @param tempSpellsKnownArray
	 * @param tempMaxSpellsPerDayArray
	 * @return
	 */
	public int[] getFreeSpellSlotsSpecial(int classNumberRepresentation) {
		int[] specificSpellsKnownArray = spellsKnownArray[classNumberRepresentation];
		int[] specificMaxSpellsArray = maxSpellsPerDayArray[classNumberRepresentation];

		int[] returnArray = new int[ConstantHelper.SPELL_LEVEL_MAX];
		for (int i = 0; i < specificSpellsKnownArray.length; i++) {
			if (specificMaxSpellsArray[i] - specificSpellsKnownArray[i] > 0)
				returnArray[i] = specificMaxSpellsArray[i] - specificSpellsKnownArray[i];
		}
		return returnArray;
	}

	/**
	 * Resets the number of spells remaining to the maximum possible values for
	 * all classes
	 */
	public void resetSpellsRemainingToMax(int classNumberRepresentation) {
		this.spellsCastsRemainingArray = copyMaxSpellsPerDayArray();

	}

	/**
	 * Gets the previous class integer representation which has been leveled up
	 * 
	 * @param startPosition
	 * @param tempCharacterClassLevelsArray
	 * @return
	 */
	public int getNextSpellBookLowToHigh(int startPosition, int[] tempCharacterClassLevelsArray) {
		int returnValue = -1;
		try {
			for (int i = startPosition; i <= characterClassLevelsArray.length; i++) {
				if (tempCharacterClassLevelsArray[i] > 0) {
					if (isMagicClass(i)) {
						returnValue = i;
						break;
					}
				}
			}
		} catch (Exception e) {
			returnValue = -1;
		}
		return returnValue;
	}

	/**
	 * Gets the next class integer representation which has been leveled up
	 * 
	 * @param startPosition
	 * @return
	 */
	public int getNextSpellBookHighToLow(int startPosition, int[] tempCharacterClassLevelsArray) {
		int returnValue = -1;
		//If out of bounds, then return negative showing 
		try {
			for (int i = startPosition - 1; i >= 0; i--) {
				if (tempCharacterClassLevelsArray[i] > 0) {
					if (isMagicClass(i)) {
						returnValue = i;
						break;
					}
				}
			}
		} catch (Exception e) {
			returnValue = -1;
		}
		return returnValue;
	}

	/**
	 * Determines if the class currently being looked at has magic
	 * 
	 * @param c
	 * @return
	 */
	private boolean isMagicClass(int c) {

		if (c == 1 || c == 2 || c == 3 || c == 6 || c == 7 || c == 9 || c == 10)
			return true;
		else
			return false;
	}

	/**
	 * Gets the maxumum spell level for the specified classNumber representation
	 * 
	 * @param classNumberRepresentation
	 * @return
	 */
	public int getMaxSpellLevelForSpecificClass(int classNumberRepresentation) {
		return maximumSpellLevels[classNumberRepresentation];
	}

	public int[] getSpellCastsRemainingForSpecificClass(int classNumberRepresentation) {
		return spellsCastsRemainingArray[classNumberRepresentation];
	}

	public void decrementSpellsRemaining(int classNumberRepresentation, int position) {
		spellsCastsRemainingArray[classNumberRepresentation][position]--;
	}

	/**
	 * @return the level
	 */
	public int getLevel() {
		return level;
	}

	/**
	 * @param level
	 *            the level to set
	 */
	public void setLevel(int level) {
		this.level = level;
	}

	/**
	 * @return the characterClassLevelsArray
	 */
	public int[] getCharacterClassLevelsArray() {
		return characterClassLevelsArray;
	}

	/**
	 * @param characterClassLevelsArray
	 *            the characterClassLevelsArray to set
	 */
	public void setCharacterClassLevelsArray(int[] characterClassLevelsArray) {
		this.characterClassLevelsArray = characterClassLevelsArray;
	}

	/**
	 * @return the classDescriptionString
	 */
	public String getClassDescriptionString() {
		return classDescriptionString;
	}

	/**
	 * @param classDescriptionString
	 *            the classDescriptionString to set
	 */
	public void setClassDescriptionString(String classDescriptionString) {
		this.classDescriptionString = classDescriptionString;
	}

	/**
	 * @return the baseAttackBonusString
	 */
	public String getBaseAttackBonusString() {
		return baseAttackBonusString;
	}

	/**
	 * @param baseAttackBonusString
	 *            the baseAttackBonusString to set
	 */
	public void setBaseAttackBonusString(String baseAttackBonusString) {
		this.baseAttackBonusString = baseAttackBonusString;
	}

	/**
	 * @return the meleeAttackBonusString
	 */
	public String getMeleeAttackBonusString() {
		return meleeAttackBonusString;
	}

	/**
	 * @param meleeAttackBonusString
	 *            the meleeAttackBonusString to set
	 */
	public void setMeleeAttackBonusString(String meleeAttackBonusString) {
		this.meleeAttackBonusString = meleeAttackBonusString;
	}

	/**
	 * @return the rangedAttackBonusString
	 */
	public String getRangedAttackBonusString() {
		return rangedAttackBonusString;
	}

	/**
	 * @param rangedAttackBonusString
	 *            the rangedAttackBonusString to set
	 */
	public void setRangedAttackBonusString(String rangedAttackBonusString) {
		this.rangedAttackBonusString = rangedAttackBonusString;
	}

	/**
	 * @return the savingThrowValues
	 */
	public int[] getSavingThrowValues() {
		return savingThrowValues;
	}

	/**
	 * @param savingThrowValues
	 *            the savingThrowValues to set
	 */
	public void setSavingThrowValues(int[] savingThrowValues) {
		this.savingThrowValues = savingThrowValues;
	}

	public int getSavingThrowFortitude() {
		return savingThrowValues[0];
	}

	public int getSavingThrowReflex() {
		return savingThrowValues[1];
	}

	public int getSavingThrowWill() {
		return savingThrowValues[2];
	}

	/**
	 * @return the characterMagicType
	 */
	public int getCharacterMagicType(int position) {
		return characterMagicType[position];
	}

	/**
	 * @param characterMagicType
	 *            the characterMagicType to set
	 */
	public void setCharacterMagicType(int[] characterMagicType) {
		this.characterMagicType = characterMagicType;
	}

	/**
	 * @return the maximumSpellLevels
	 */
	public int[] getMaximumSpellLevels() {
		return maximumSpellLevels;
	}

	/**
	 * @param maximumSpellLevels
	 *            the maximumSpellLevels to set
	 */
	public void setMaximumSpellLevels(int[] maximumSpellLevels) {
		this.maximumSpellLevels = maximumSpellLevels;
	}

	/**
	 * @return the maxSpellsPerDayArray
	 */
	public int[][] getMaxSpellsPerDayArray() {
		return maxSpellsPerDayArray;
	}

	/**
	 * @param maxSpellsPerDayArray
	 *            the maxSpellsPerDayArray to set
	 */
	public void setMaxSpellsPerDayArray(int[][] maxSpellsPerDayArray) {
		this.maxSpellsPerDayArray = maxSpellsPerDayArray;
	}

	/**
	 * @return the spellsCastsRemainingArray
	 */
	public int[][] getSpellsCastsRemainingArray() {
		return spellsCastsRemainingArray;
	}

	/**
	 * @param spellsCastsRemainingArray
	 *            the spellsCastsRemainingArray to set
	 */
	public void setSpellsCastsRemainingArray(int[][] spellsCastsRemainingArray) {
		this.spellsCastsRemainingArray = spellsCastsRemainingArray;
	}

	/**
	 * @return the spellsKnownArray
	 */
	public int[][] getSpellsKnownArray() {
		return spellsKnownArray;
	}

	/**
	 * @param spellsKnownArray
	 *            the spellsKnownArray to set
	 */
	public void setSpellsKnownArray(int[][] spellsKnownArray) {
		this.spellsKnownArray = spellsKnownArray;
	}

	public String getBeginningClass() {
		return this.beginningClass;
	}

	public void setBeginningClass(String beginningClass) {
		this.beginningClass = beginningClass;
	}

	public void setSpellListItemArray(ArrayList<SpellListItem> spellListItemArray) {
		this.spellListItemArray = spellListItemArray;
	}

	public ArrayList<SpellListItem> getSpellListItemArray() {
		return spellListItemArray;
	}

	public void addSpellListItem(SpellListItem sli) {
		this.spellListItemArray.add(sli);
	}

	public void removeSpellListItem(SpellListItem sli) {
		this.spellListItemArray.remove(sli);
	}

	public void clearSPellListItem() {
		this.spellListItemArray.clear();
	}

	public void setHasBeenCastArray(boolean[][] hasBeenCastArray) {
		this.hasBeenCastArray = hasBeenCastArray;
	}

	public boolean[][] getHasBeenCastArray() {
		return hasBeenCastArray;
	}

	public boolean gethasBeenCastArrayElement(int groupPos, int childPos) {
		return hasBeenCastArray[groupPos][childPos];
	}

	public void setHasBeenCastArrayElement(int groupPos, int childPos, boolean value) {
		this.hasBeenCastArray[groupPos][childPos] = value;
	}

}
